package com.lww.smartbathroom.service.impl;

import com.lww.smartbathroom.model.Equipment;
import com.lww.smartbathroom.model.User;
import com.lww.smartbathroom.param.EquipmentQueryParam;
import com.lww.smartbathroom.service.EquipmentService;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.apache.tomcat.jni.Local;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.function.LongSupplier;

/**
 * @author lww
 * @version 1.0.0
 * @ClassName EquipmentServiceImpl.java
 * @Description TODO
 * @createTime 2021年01月24日 13:31:00
 */
@Service
public class EquipmentServiceImpl implements EquipmentService {

    private static final Logger LOG = LoggerFactory.getLogger(EquipmentServiceImpl.class);
    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public Equipment add(Equipment equipment) {
        if (equipment == null) {
            LOG.error("input equipment is null");
            return  null;
        }
        if (equipment.getGmtCreated()==null){
            equipment.setGmtCreated(LocalDateTime.now());

        }
        if (equipment.getGmtModified()==null){
            equipment.setGmtModified(LocalDateTime.now());
        }
        return mongoTemplate.insert(equipment);
    }

    @Override
    public Equipment get(String id) {
        if (!StringUtils.hasText(id)){
            LOG.error("input equipmentId is null");
            return null;
        }
        return mongoTemplate.findById(id,Equipment.class);
    }

    @Override
    public Page<Equipment> list(EquipmentQueryParam param) {
        // 作为服务，要对入参进行判断，不能假设被调用时，入参一定正确
        if (param == null) {
            LOG.error("input param data is not correct.");
            return null;
        }

        // 总条件
        Criteria criteria = new Criteria();
        // 可能有多个子条件
        List<Criteria> subCris = new ArrayList();
        if (StringUtils.hasText(param.getLocation())) {
            subCris.add(Criteria.where("location").is(param.getLocation()));
        }

        if (param.getStatus()!=null) {
            subCris.add(Criteria.where("status").is(param.getStatus()));
        }

        // 必须至少有一个查询条件
        if (!subCris.isEmpty()) {
            // 三个子条件以 and 关键词连接成总条件对象，相当于 name='' and lyrics='' and subjectId=''
            criteria.andOperator(subCris.toArray(new Criteria[] {}));
        }


        // 条件对象构建查询对象
        Query query = new Query(criteria);
        // 总数
        long count = mongoTemplate.count(query, Equipment.class);
        // 构建分页对象。注意此对象页码号是从 0 开始计数的。
        Pageable pageable = PageRequest.of(param.getPagination() - 1, param.getPageSize());
        query.with(pageable);

        // 查询结果
        List<Equipment> equipments = mongoTemplate.find(query, Equipment.class);
        // 构建分页器
        Page<Equipment> pageResult = PageableExecutionUtils.getPage(equipments, pageable, new LongSupplier() {
            @Override
            public long getAsLong() {
                return count;
            }
        });

        return pageResult;
    }

    @Override
    public boolean modify(Equipment equipment) {
        if (equipment == null||!StringUtils.hasText(equipment.getId())) {
            LOG.error("input epuipment is null or id is null");
            return false;
        }
        // 主键不能修改，作为查询条件
        Query query = new Query(Criteria.where("_id").is(equipment.getId()));

        Update update = new Update();
        if (equipment.getIndex()!=null){
            update.set("index",equipment.getIndex());

        }
        if (equipment.getStatus() != null) {
            update.set("status",equipment.getStatus());
        }
        if (equipment.getLocation()!=null){
            update.set("location",equipment.getLocation());
        }
        if (equipment.getTime()!=null){
            update.set("time",equipment.getTime());
        }

        if (equipment.getStartTime()!=null){
            update.set("startTime",equipment.getStartTime().plusMinutes(equipment.getTime()));
        }
        UpdateResult updateResult = mongoTemplate.updateFirst(query,update,Equipment.class);

        return updateResult!=null&&updateResult.getModifiedCount()>0;
    }

    @Override
    public boolean delete(String id) {
        if (!StringUtils.hasText(id)){
            LOG.error("input equipmentId is null");
            return false;
        }
        Equipment equipment = new Equipment();
        equipment.setId(id);

        DeleteResult result = mongoTemplate.remove(equipment);
        return result != null && result.getDeletedCount() > 0;
    }

    @Override
    public long count() {
        return mongoTemplate.findAll(Equipment.class).size();
    }
}
